package cn.itcast.nems.studentrecord.dao.mapper;

import cn.itcast.nems.common.bean.KeyValue;
import cn.itcast.nems.employee.dao.bean.EmployeeGroupBean;
import cn.itcast.nems.studentrecord.dao.condition.StudentRecordParams;
import cn.itcast.nems.studentrecord.dao.condition.SuspendStudentQuery;
import cn.itcast.nems.studentrecord.dao.dataobject.*;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Mapper
public interface StudentRecordMapper extends BaseMapper<StudentRecord> {

    
    
    /**
     * <p>
     * 根据班级ID 统计出班、重读、结课和休学等状态数量
     * </p>
     *
     * @author zhouwei
     * @since 2024/3/15 4:53 PM
     **/
    List<StudentRecordDO> statisticsCountByClazzId(@Param("clazzId") Integer clazzId) ;

    /**
     * <p>
     * 根据班级查询学籍列表
     * </p>
     *
     * @param recordDO 查询参数
     * @author zhouwei
     * @since 2024/3/12 3:00 PM
     **/
    List<StudentRecordDO> queryStudentRecordListByParams(@Param("recordDO") StudentRecordDO recordDO) ;

    /**
     * 根据学员ID查询已生效的学籍列表
     * @param studentId 学员ID
     * @return 生效的学籍列表， 根据开班时间倒序， 为空返回 null
     */
    List<StudentRecordDO> findValidStudentRecordByStudentId(@Param("studentId") Integer studentId ) ;
    /**
     * <p>
     * 根据学生ID班级ID查询学籍信息
     * </p>
     *
     * @param studentIds 学生ID 老EMS student 表主键
     * @param clazzIds 班级ID
     * @author zhouwei
     * @since 2024/2/23 9:20 AM
     **/
    List<StudentRecordDO> queryByStudentIdAndClassId(@Param("studentIds") Set<Integer> studentIds , @Param("clazzIds") Set<Integer> clazzIds) ;

    /**
     * 根据学籍ID查询学员ID
     * @param studentRecordIds 学籍ID
     * @return 学籍及学员ID，key:["studentRecordId", "studentId"] value:[studentRecordId, studentId]
     */
    List<Map<String, Object>> findStudentIds(@Param("studentRecordIds") Set<String> studentRecordIds);
    
    /**
     * 
     * 功能描述：获取指定学籍的学生ID
     *
     * @param id 学籍ID
     * @return 学生ID
     * 
     * @author 刘曙
     *
     * @since 2024年3月19日
     *
     * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
     */
    Integer getStudentIdByID(@Param("id") String id);

    /**
     * 查询学生ID对应的学籍列表
     * @param studentId 学生ID
     * @param excludeIds 需要过滤的学籍ID
     * @return 学籍列表 ， 为空返回null
     */
    List<StudentRecord> findStudentRecordListByStudentId(@Param("studentId") Integer studentId, @Param("excludeIds") Set<String> excludeIds) ;

    /**
     * 查询班级有效学籍数
     *
     * @param clazzId    班级ID
     * @param maxOutDate 最大出班日期；出班日期小于该值的算有效学籍，如果为空忽略出班日期
     * @return 有效学籍数
     */
    int selectValidStudentRecordCount(@Param("clazzId") int clazzId, @Param("maxOutDate") LocalDateTime maxOutDate);

    /**
     * <p>
     * 统计指定班级ID学籍缴费记录（未缴费、部分缴费、欠费总金额和已缴费人数  ）
     * </p>
     *
     * @param  clazzId 班级ID
     * @author zhouwei
     * @since 2023/12/20 1:44 PM
     **/
    StudentRecordCountDO findCountByClazzId(@Param("clazzId") Integer clazzId) ;
    /**
     * <p>
     * 查询班级在途学籍列表
     * </p>
     *
     * @param clazzId 班级ID
     * @param ids 学籍ID 
     * @return 在途学籍列表， 没有数据返回 null
     * @author zhouwei
     * @since 2024/1/12 9:52 AM
     **/
    List<ClazzLockRecordDO> findClazzLockRecordListByClazzId(@Param("clazzId") Integer clazzId , @Param("ids") List<String> ids) ;

    /**
     * <p>
     * 根据学生ID查询关联的班级
     * </p>
     *
     * @param studentRecordParams  查询参数
     * @param upgradeable 是否升级就业班
     * @return 关联的班级列表
     * @author zhouwei
     * @since 2023/12/14 3:25 PM
     **/
    List<StudentClazzDO> findClazzByStudentId(
            @Param("studentRecordParams") StudentRecordParams studentRecordParams,
            @Param("delayFlag") Boolean delayFlag,
            @Param("suspensionFlag") Boolean suspensionFlag,
            @Param("upgradeable") Boolean upgradeable ,
            @Param("employeeGroups")  List<EmployeeGroupBean> employeeGroups
    ) ;

    /**
     * 查找给定日期的出班（结算日期）的学籍
     *
     * @param startDateTime 出班（结算）开始时间
     * @param endDateTime   出班（结算）结束时间
     * @return 学籍
     */
    List<StudentRecord> selectOutStudentRecords(@Param("startDateTime") LocalDateTime startDateTime,
                                                @Param("endDateTime") LocalDateTime endDateTime);

    /**
     * 根据订单ID查询对应的学籍
     *
     * @param orderId 订单ID
     * @return 学籍
     */
    StudentRecord selectStudentRecordByOrderId(@Param("orderId") String orderId);

    /**
     * 查询未出班的有效学籍信息
     *
     * @param studentId 学员ID
     * @param clazzId   班级ID
     * @return 学籍
     */
    StudentRecord selectInClazzByStudentIdClazzId(@Param("studentId") Integer studentId, @Param("clazzId") Integer clazzId);

    /**
     * 根据学员ID和班级ID查询学籍（包括失效的和已出班的）
     *
     * @param studentId 学员ID
     * @param clazzId   班级ID
     * @return 学籍
     */
    List<StudentRecord> selectByStudentIdClazzId(@Param("studentId") Integer studentId, @Param("clazzId") Integer clazzId);

    /**
     * 查询一批学籍的锁定状态
     *
     * @param studentRecordIds 学籍ID
     * @return key:studentRecordId value:lockFlag
     */
    List<KeyValue<String, Boolean>> selectLockFlags(@Param("studentRecordIds") Set<String> studentRecordIds);

    /**
     * 修改学籍的锁定状态
     *
     * @param studentRecordIds 学籍ID
     * @param lockFlags        锁定标记
     * @param modifiedBy       修改人
     */
    void updateLockFlags(@Param("studentRecordIds") Set<String> studentRecordIds,
                         @Param("lockFlags") boolean lockFlags,
                         @Param("modifiedBy") String modifiedBy);

    /**
     * 学籍 分页查询
     *
     * @param page     分页参数
     * @param recordDO 搜索条件
     * @return 分页结果
     */
    @InterceptorIgnore(tenantLine = "true")
    IPage<StudentRecordDO> findPageList(Page<StudentRecordDO> page, @Param("recordDO") StudentRecordDO recordDO);

    /**
     * 根据 EMS studentId 查询学籍
     *
     * @param studentId EMS 学生ID
     * @return 学籍
     **/
    @InterceptorIgnore(tenantLine = "true")
    StudentRecordDO findByRelationId(@Param("studentId") Integer studentId);

    /**
     * 根据学籍号和班级ID查询学籍详情
     *
     * @param no      学籍号
     * @param clazzId 班级ID
     * @return 学籍详情
     */
    @Select("select * from student_record where no=#{no} and clazz_id=#{clazzId} order by created_datetime desc limit 1")
    StudentRecord findByNOAndClazzId(@Param("no") String no, @Param("clazzId") String clazzId);

    /**
     * 生效学籍并累加金额
     *
     * @param studentRecordId 学籍ID
     * @param paidAmount      本次支付金额(单位:分)
     * @return 影响行数
     */
    int effectAndAccumulatePaidAmount(@NonNull @Param("studentRecordId") String studentRecordId,
                                      @Nullable @Param("paidAmount") Integer paidAmount);

    /**
     * 查詢指定班級部分支付的学籍列表
     *
     * @param clazzId 班级ID
     * @return 学籍列表
     */
    List<StudentRecordDO> findPayingStudentRecordList(@Param("clazzId") Integer clazzId);

    /**
     * 查詢指定班級完全支付的学籍列表
     *
     * @param clazzId 班级ID
     * @return 学籍列表
     */
    List<StudentRecordDO> findPaidStudentRecordList(@Param("clazzId") Integer clazzId);

    /**
     * 根据班级ID、支付状态或学籍查询缴费情况
     *
     * @param recordParam
     * @return
     */
    List<StudentRecordDO> findStudentRecordListByCondition(@Param("recordParam") StudentRecordParams recordParam);

    /**
     * 修改学籍调整金额
     *
     * @param studentRecordId  学籍ID
     * @param adjustmentAmount 调整金额
     * @author 高昌露
     * @since 2023/11/23 17:15
     */
    void updateAdjustmentAmount(@NonNull @Param("studentRecordId") String studentRecordId,
                                @NonNull @Param("adjustmentAmount") Integer adjustmentAmount);

    /**
     * 根据学籍ID查询学籍关联的所有订单号
     *
     * @param studentRecordId 学籍ID
     * @return java.util.List<java.lang.String> 订单ID集合
     * @author 高昌露
     * @since 2023/11/24 9:24
     */
    List<String> queryOrderIdsByStudentRecordId(@NonNull String studentRecordId);

    /**
     * 根据学籍ID查询校区ID
     *
     * @param recordDO
     * @return
     */
    @InterceptorIgnore(tenantLine = "true")
    List<String> findSchoolIdsByRecordId(@NonNull @Param("recordDO") StudentRecordDO recordDO);

    List<StudentRecordInfoDO> listStudentRecordInfo(@Param("studentId") Integer studentId, @Param("clazzId") Integer clazzId, @Param("studentRecordId") String studentRecordId);

    /**
     * 根据班级ID统计出班时间为空的学籍数量
     * @param clazzId 班级ID
     * @return int 总数
     */
    int findInClazzCount(@Param("clazzId") Integer clazzId) ;

    IPage<SpecialClazz> findSpecialClazzPage(@Param("params") SpecialClazzQuery condition, Page<Object> of);

    SpecialClazz findSpecialClazzById(@Param("clazzId") Integer clazzId);

    List<SpecialClazz> searchSpecialClazz(@Param("params") SpecialClazzQuery query);

    Page<StudentRecord> findStudentRecordPage(Page<StudentRecord> page, @Param("query") SuspendStudentQuery query);

    List<StudentRecordInfoDO> listStudentRecordInfoByjournalRefundId(@Param("studentRecordId") String studentRecordId, @Param("clazzId") Integer clazzId);


    /**
     * <p>
     * 根据班级ID 查询进班时间早于开班时间、且非锁定的学籍列表
     * </p>
     *
     * @param clazzId 班级ID
     * @param startDate 修改后的开班时间
     * @return 学籍列表 , 没有则返回 null
     * @author zhouwei
     * @since 2023/12/26 4:10 PM
     **/
    List<StudentRecordDO> findBeforeStartDateByClazzId(
            @Param("clazzId") Integer clazzId, @Param("startDate") String startDate);
    
    /**
     * <p>
     * 统计缴费情况（定时人数）
     * </p>
     *
     * @param isAll  是否查询全部时间段
     * @param startTime 起始时间
     * @return 学籍列表 , 没有则返回 null
     * @author zhouwei
     * @since 2023/12/26 4:10 PM
     **/
    List<StudentRecordCountDO> findAllClazzEnrolmentCount(@Param("isAll") Boolean isAll ,@Param("startTime") LocalDateTime startTime ) ;

    /**
     * 
     * 功能描述：获取指定班级的所有在读学籍（不含未生效和已出班学籍）
     *
     * @param clazzId 班级ID
     * @return 在读学籍列表（含学生基础信息）
     * 
     * @author 刘曙
     *
     * @since 2024年1月4日
     *
     * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
     */
    List<StudentRecordWithStudentDO> selectInclazzByClazzId(@Param("clazzId") Integer clazzId);

    /**
     * 查询凭单
     *
     * @param recordId
     * @return
     */
    List<StudentRecordJournalVoModel> findStudentRecordJournals(@Param("recordId") String recordId);

    List<ClassInfoDO> getClassInfos(@Param("accountId") String accountId,
                                    @Param("includePending") boolean includePending,
                                    @Param("includeDeleted") boolean includeDeleted,
                                    @Param("isGraduation") boolean isGraduation);

    List<ClassInfoDO> getClassInfosTeacher(@Param("email") String email,
                                    @Param("includePending") boolean includePending,
                                    @Param("includeDeleted") boolean includeDeleted,
                                    @Param("isGraduation") boolean isGraduation);
}
